<?php

/**
 * Base_AdminObject - Admin object
 *
 * @package
 * @author Alexis Eric, Erra Prod
 * @copyright Copyright (c) 2012 - Erra Prod
 * @version $1.0$
 * @access public
 */
class Base_NavigationObject extends Erra_Fields_Base_Object {

    protected $navigationRawData = null;
    protected $pageObjectData = null;
    protected $tagList = array('active' => 'class="current"',
        'root' => array('tag' => 'ul'),
        'level1' => array('tag' => 'li', 'section' => 'ul'),
        'level2' => array('tag' => 'li', 'section' => 'ul'),
        'level3' => array('tag' => 'li', 'section' => 'ul'));

    public function __construct($id, $buildArgs = null) {
        parent::__construct($id, $buildArgs);
        $navigationName = (is_null($buildArgs)) ? 'main_navigation' : $buildArgs;

        // Get site page data
        $pages = Base_LayoutObject::getList(null, null, 'ALL');
        $pageObjectData = $pages->getObjectDataArray();

        // Get navigation data if exists
        $navigationRawData = Erra_Core_DatabasePdo::_SELECT('SELECT erra__navigation_data FROM ' . $this->getTableName() . ' WHERE object_id="' . $this->getObjectId() . '"');
        if (Erra_Core_DatabasePdo::rowCount() && is_object($navigationRawData)) {
            $row = $navigationRawData->fetch();
            $navigationRawData = self::buildNavigation($row['erra__navigation_data']);
            self::addMissingPages($pageObjectData, $navigationRawData);
        } else {
            $navigationRawData = array();
        }

        $this->pageObjectData = $pageObjectData;
        $this->navigationRawData = $navigationRawData;

        $nestedSortableHtml = self::renderNestedSortable($navigationRawData, $pageObjectData);
        $this->prepend($nestedSortableHtml);

        $navigation_data = Erra_Fields_Hidden::create('erra__navigation_data');
        $this->addField($navigation_data);
        $this->setDescription(__('Navigation tree handling') . ' - ' . $this->getObjectId());
    }

    public function setTag($elementName, $tagValues) {
        if (isset($this->tagList[$elementName])) {
            if (is_array($this->tagList[$elementName])) {
                $this->tagList[$elementName] = array_replace($this->tagList[$elementName], $tagValues);
            } else {
                $this->tagList[$elementName] = $tagValues;
            }
        }
        return $this;
    }

    public function getPage($id) {
        if (is_array($this->pageObjectData)) {
            foreach ($this->pageObjectData as $a_page) {
                if ($a_page['id'] == $id) {
                    return $a_page;
                }
            }
        }
        return null;
    }

    public function getElement($elementName, $tagItem = null, $tagValue=null, $activeClass=null) {
        if ($tagValue == null && $tagItem == null) {
            return (isset($this->tagList[$elementName])) ? $this->tagList[$elementName] : '';
        }
        if (isset($this->tagList[$elementName]) && is_array($this->tagList[$elementName]) && isset($this->tagList[$elementName][$tagItem])) {
            $object = $this->tagList[$elementName];
            $id = isset($object['id']) ? ' id="' . $object['id'] . '" ' : '';
            $class = isset($object['class']) ? ' class="' . $object['class'] . '" ' : '';
            if ($tagValue == 'open') {
                return '<' . $object[$tagItem] . $id . $class . ' ' . $activeClass . '>';
            }
            if ($tagValue == 'close') {
                return '</' . $object[$tagItem] . '>';
            }
        }
        return '';
    }

    function getNavigationTreeRecursiveAjax($navigationData, $maxRecursionLevel, $recursionLevel=0) {
        $res = '';

        $currentRouteName = Erra_System_PageBuilder::getCurrentPage();
        $currentRouteName = $currentRouteName['routeName'];
        if (is_array($navigationData) && count($navigationData) && $recursionLevel < $maxRecursionLevel) {
            $res .= $this->getElement('level' . $recursionLevel, 'section', 'open');
            foreach ($navigationData as $pageElementId => $deeperPages) {
                $urlMachine = $this->getPage($pageElementId);
                if ($urlMachine['exclude_from_navigation'] != 'yes') {
                    $res .= $this->getElement('level' . ($recursionLevel + 1), 'tag', 'open');
                    $urlMachine = $urlMachine['page_url'];
                    $active = ($urlMachine == $currentRouteName) ? $this->getElement('active') : '';
                    $res .= '<a  ' . $active . ' href="' . Erra_System_PageBuilder::makeAjaxLink($urlMachine) . '">' . Erra_System_PageBuilder::friendlyTitle($urlMachine) . '</a>';
                    $res .= $this->getNavigationTreeRecursiveAjax($deeperPages, $maxRecursionLevel, ($recursionLevel + 1));
                    $res .= $this->getElement('level' . ($recursionLevel + 1), 'tag', 'close', $active);
                }
            }
            $res .= $this->getElement('level' . $recursionLevel, 'section', 'close');
        }
        return $res;
    }

    public function getNavigationTreeAjax($maxRecursionLevel=100) {
        $res = $this->getElement('root', 'tag', 'open');
        $res .= $this->getNavigationTreeRecursiveAjax($this->navigationRawData, $maxRecursionLevel);
        $res .= $this->getElement('root', 'tag', 'close');
        return $res;
    }

    
    function getNavigationTreeRecursive($navigationData, $maxRecursionLevel, $recursionLevel=0) {
        $res = '';

        $currentRouteName = Erra_System_PageBuilder::getCurrentPage();
        $currentRouteName = $currentRouteName['routeName'];
        if (is_array($navigationData) && count($navigationData) && $recursionLevel < $maxRecursionLevel) {
            $res .= $this->getElement('level' . $recursionLevel, 'section', 'open');
            foreach ($navigationData as $pageElementId => $deeperPages) {
                $urlMachine = $this->getPage($pageElementId);
                if ($urlMachine['exclude_from_navigation'] != 'yes') {
                    $res .= $this->getElement('level' . ($recursionLevel + 1), 'tag', 'open');
                    $urlMachine = $urlMachine['page_url'];
                    $active = ($urlMachine == $currentRouteName) ? $this->getElement('active') : '';
                    $res .= '<a  ' . $active . ' href="' . Erra_System_PageBuilder::makeLink($urlMachine) . '">' . Erra_System_PageBuilder::friendlyTitle($urlMachine) . '</a>';
                    $res .= $this->getNavigationTreeRecursive($deeperPages, $maxRecursionLevel, ($recursionLevel + 1));
                    $res .= $this->getElement('level' . ($recursionLevel + 1), 'tag', 'close', $active);
                }
            }
            $res .= $this->getElement('level' . $recursionLevel, 'section', 'close');
        }
        return $res;
    }

    public function getNavigationTree($maxRecursionLevel=100) {
        $res = $this->getElement('root', 'tag', 'open');
        $res .= $this->getNavigationTreeRecursive($this->navigationRawData, $maxRecursionLevel);
        $res .= $this->getElement('root', 'tag', 'close');
        return $res;
    }

    public static function buildNavigation($data) {
//list[55]=root&list[2]=root&list[3]=2&list[4]=2&list[5]=2&list[6]=2&list[7]=root&list[8]=root&list[9]=root&list[10]=root&list[11]=10&list[12]=10&list[13]=10&list[14]=10&list[15]=root&list[16]=root
        $data = explode('&', trim($data));
        $result = array();

// Buld root elements first
        foreach ($data as $item) {
            if (strstr($item, '=root')) {
                $id_value = str_replace(array('list[', ']', '=root'), array('', '', ''), $item);
                $result[$id_value] = null;
            }
        }

// level 1
        foreach ($data as $item) {
            foreach ($result as $level_1_key => &$level_1_item) {
                if (strstr($item, '=' . $level_1_key) && strlen($item) == (strpos($item, '=') + strlen('=' . $level_1_key))) {
                    if (is_null($level_1_item)) {
                        $level_1_item = array();
                    }
                    $id_value = str_replace(array('list[', ']=' . $level_1_key), array('', ''), $item);
                    $level_1_item[$id_value] = '';
                }
            }
        }
// level 2
        foreach ($data as $item) {
            foreach ($result as $level_1_key => &$level_1_item) {
                if (is_array($level_1_item)) {
                    foreach ($level_1_item as $level_2_key => &$level_2_item) {
                        if (strstr($item, '=' . $level_2_key) && strlen($item) == (strpos($item, '=') + strlen('=' . $level_2_key))) {
                            if (is_string($level_2_item)) {
                                $level_2_item = array();
                            }
                            $id_value = str_replace(array('list[', ']=' . $level_2_key), array('', ''), $item);
                            $level_2_item[$id_value] = '';
                        }
                    }
                }
            }
        }
        return $result;
    }

    public static function addMissingPages($pageObjectData, &$navigation) {

        foreach ($pageObjectData as $aPageData) {
            $id = $aPageData['id'];
            if (!in_arrayr($id, array_keysr($navigation))) {
                $navigation[$id] = '';
            }
        }
    }

    public static function renderNestedSortable($navigation, $pageData) {
        // Get prototype field for filling data
        $aFieldClone = new Base_LayoutObject('prototype');
        $res = '';
        $res .= '<ol class="sortable">';
        if (empty($navigation)) {
            foreach ($pageData as $position => $aFieldData) {
                $res .= Base_NavigationObject::renderRow($aFieldClone, $aFieldData, $position, $pageData);
            }
        } else {
            $positionCounter = 0;
            foreach ($navigation as $itemId => $itemData) {
                if (is_array($itemData)) {
                    $res .= Base_NavigationObject::renderRow($aFieldClone, $itemId, $positionCounter, $pageData);
                    $res .= '<ol>';
                    $positionCounterLevel1 = 0;
                    foreach ($itemData as $idLevel1 => $dataLevel1) {
                        if (is_array($dataLevel1)) {
                            $res .= Base_NavigationObject::renderRow($aFieldClone, $idLevel1, $positionCounterLevel1, $pageData);
                            $res .= '<ol>';
                            $positionCounterLevel2 = 0;
                            foreach ($dataLevel1 as $idLevel2 => $dataLevel2) {
                                $res .= Base_NavigationObject::renderRow($aFieldClone, $idLevel2, $positionCounterLevel2, $pageData);
                                $positionCounterLevel2++;
                            }
                            $res .= '</ol>';
                        } else {
                            $res .= Base_NavigationObject::renderRow($aFieldClone, $idLevel1, $positionCounterLevel1, $pageData);
                        }
                        $positionCounterLevel1++;
                    }
                    $res .= '</ol>';
                } else {
                    $res .= Base_NavigationObject::renderRow($aFieldClone, $itemId, $positionCounter, $pageData);
                }
                $positionCounter++;
            }
        }
        $res .= '</ol>';
        return $res;
    }

    public static function renderRow($aFieldClone, $aFieldData, $position, $pageData=null) {
        if (!is_null($pageData)) {
            foreach ($pageData as $data) {
                if (isset($data['id']) && $data['id'] == $aFieldData) {
                    $aFieldData = $data;
                }
            }
        }
        $res = '<li id="list_' . $aFieldData['id'] . '">';
        $res .= '<div>';
        $aFieldClone->setCrud('RU');
        $res .= Erra_System_FormRenderer::_editTableHeader($aFieldClone, $aFieldData, $position);
        $res .= Erra_System_FormRenderer::_editRow($aFieldClone, $aFieldData, $position, 'AdminController/saveSqlReload');
        $res .= Erra_System_FormRenderer::_editTableClosure();
        $res .= '</div>' . "\n";
        return $res;
    }

    public function getTableName() {
        return 'ufm__navigation';
    }

}

?>